package com.captjack.micro.dao.database.configuration;

import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.incrementer.OracleKeyGenerator;
import com.baomidou.mybatisplus.mapper.LogicSqlInjector;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * Description description.....
 *
 * @author Jack Sparrow
 * @version 1.0.0
 * @date 2018/6/13 23:11
 * package com.captjack.micro.dao.database.mapper
 */
@Configuration
@MapperScan(basePackages = "com.captjack.micro.dao.database.mapper")
@EnableTransactionManagement
public class MybatisPlusConfiguration {

    /**
     * @return 数据源
     */
    @Bean(name = "mysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    DataSource mysqlDataSource() {
        return new HikariDataSource();
    }

    /**
     * 这里全部使用mybatis-autoconfigure 已经自动加载的资源。不手动指定
     * 配置文件和mybatis-boot的配置文件同步
     *
     * @return MybatisSqlSessionFactoryBean
     * @throws IOException 异常
     */
    @Bean
    public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean(@Qualifier(value = "mysqlDataSource") DataSource dataSource) throws IOException {
        // mybatis-plus配置
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        // mybaties-plus全局配置
        mybatisSqlSessionFactoryBean.setGlobalConfig(getMybatiesPlusGlobalConfiguration());
        // 数据源
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        // MapperLocations
        mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/captjack/micro/dao/database/mapper/xml/*Mapper.xml"));
        // 配置扫描包名
        mybatisSqlSessionFactoryBean.setTypeAliasesPackage("com.captjack.micro.dao.database.entity");
        // mybaties配置
        mybatisSqlSessionFactoryBean.setConfiguration(getMybatiesConfiguration());
        return mybatisSqlSessionFactoryBean;
    }

    /**
     * @return mybaties-plus全局配置
     */
    private GlobalConfiguration getMybatiesPlusGlobalConfiguration() {
        GlobalConfiguration globalConfiguration = new GlobalConfiguration();
        // 主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
        globalConfiguration.setIdType(3);
        // 字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
        globalConfiguration.setFieldStrategy(2);
        // 驼峰下划线转换
        globalConfiguration.setDbColumnUnderline(true);
        // mp2.3+ 全局表前缀 mp_
        globalConfiguration.setTablePrefix("");
        // 数据库大写下划线转换
        globalConfiguration.setCapitalMode(false);
        // 刷新mapper 调试神器
        globalConfiguration.setRefresh(false);
        // Sequence序列接口实现类配置
        globalConfiguration.setKeyGenerator(new OracleKeyGenerator());
        // 逻辑删除配置（下面3个配置）
        globalConfiguration.setLogicDeleteValue("1");
        globalConfiguration.setLogicNotDeleteValue("0");
        globalConfiguration.setSqlInjector(new LogicSqlInjector());
        // 自定义填充策略接口实现
//        globalConfiguration.setMetaObjectHandler();
        return globalConfiguration;
    }

    /**
     * @return mybaties配置
     */
    private MybatisConfiguration getMybatiesConfiguration() {
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        // 设置映射驱动方式
        mybatisConfiguration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        // 配置JdbcTypeForNull, oracle数据库必须配置
        mybatisConfiguration.setJdbcTypeForNull(JdbcType.NULL);
        // 配置返回数据库(column下划线命名&&返回java实体是驼峰命名)，自动匹配无需as（没开启这个，SQL需要写as： select user_id as userId）
        mybatisConfiguration.setMapUnderscoreToCamelCase(true);
        // 开启二级缓存
        mybatisConfiguration.setCacheEnabled(true);
        // 配置sql打印
//        mybatisConfiguration.setLogImpl(StdOutImpl.class);
        return mybatisConfiguration;
    }

    /**
     * 分页插件，自动识别数据库类型
     */
    @Bean
    PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * mysql事务管理
     *
     * @param dataSource 数据源
     * @return 事务管理器
     */
    @Bean(name = "mysqlTxManager")
    protected PlatformTransactionManager mysqlTxManager(@Qualifier(value = "mysqlDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 注入数据源
     *
     * @param dataSource mysql数据源
     * @return JdbcTemplate
     */
    @Bean(name = "mysqlJdbcTemplate")
    protected JdbcTemplate mysqlJdbcTemplate(@Qualifier(value = "mysqlDataSource") DataSource dataSource) throws Exception {
        return new JdbcTemplate(dataSource);
    }

    /**
     * 注入数据源
     *
     * @param dataSource mysql数据源
     * @return NamedParameterJdbcTemplate
     */
    @Bean(name = "mysqlNamedParameterJdbcTemplate")
    protected NamedParameterJdbcTemplate mysqlNamedParameterJdbcTemplate(@Qualifier(value = "mysqlDataSource") DataSource dataSource) throws Exception {
        return new NamedParameterJdbcTemplate(dataSource);
    }

}
